package com.quanyue.music.file.service.impl;

import com.quanyue.music.domain.constant.FMChannel;
import com.quanyue.music.domain.constant.StatisticsType;
import com.quanyue.music.domain.constant.TimeZoneType;
import com.quanyue.music.file.mapper.StatisticsMapper;
import com.quanyue.music.file.service.ExcelService;
import com.quanyue.music.file.type.ExcelFileRequest;
import com.quanyue.music.file.type.FMDetailLikeResult;
import com.quanyue.music.file.type.ZoneCount;
import jxl.Workbook;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

@Service
public class ExcelServiceImpl implements ExcelService {
    private final String path = "/opt/music/admin/server/static/dist/excel";
    @Autowired
    private StatisticsMapper statisticsMapper;

    @Override
    public String exportFile(ExcelFileRequest request) {
        List <FMDetailLikeResult> resultList =
                this.fmDetail(request.getDate(), request.getChannelNum(), request.getStatisticsType());
        return this.createExcel(resultList, request);
    }

    @Override
    public String exportChannelFile(String date, FMChannel fmChannel) {
        try {
            String fileName = "statistics_" + fmChannel.name() + ".xls";
            File file = new File(path);
            if (!file.exists()) {
                file.mkdirs();
            }
            //  打开文件
            WritableWorkbook book = Workbook.createWorkbook(new File(path + "/", fileName));
            //  生成名为“第一页”的工作表，参数0表示这是第一页
            WritableSheet sheet = book.createSheet(" 第一页 ", 0);

            //  将定义好的单元格添加到工作表中  在Label对象的构造子中指名单元格位置是第一列第一行(0,0)
            sheet.addCell(new Label(0, 0, "日期"));
            sheet.addCell(new Label(1, 0, "时间"));
            sheet.addCell(new Label(2, 0, "电台"));
            sheet.addCell(new Label(3, 0, "Segment ID"));
            sheet.addCell(new Label(4, 0, "Insert ID"));
            sheet.addCell(new Label(5, 0, "收听合计"));
            sheet.addCell(new Label(6, 0, "收听PDT"));
            sheet.addCell(new Label(7, 0, "收听MDT"));
            sheet.addCell(new Label(8, 0, "收听CDT"));
            sheet.addCell(new Label(9, 0, "收听EDT"));
            sheet.addCell(new Label(10, 0, "点赞合计"));
            sheet.addCell(new Label(11, 0, "点赞PDT"));
            sheet.addCell(new Label(12, 0, "点赞MDT"));
            sheet.addCell(new Label(13, 0, "点赞CDT"));
            sheet.addCell(new Label(14, 0, "点赞EDT"));

            int row = 1;
            List <FMDetailLikeResult> resultLister = this.fmDetail(LocalDate.parse(date), fmChannel, StatisticsType.LISTER);
            List <FMDetailLikeResult> resultLike = this.fmDetail(LocalDate.parse(date), fmChannel, StatisticsType.LIKE);
            for (FMDetailLikeResult result : resultLister) {
                int column = 0;
                sheet.addCell(new Label(column++, row, date));
                sheet.addCell(new Label(column++, row, result.getStartTime().toLocalTime().toString() + "-" + result.getEndTime().toLocalTime().toString()));
                sheet.addCell(new Label(column++, row, fmChannel.name()));
                sheet.addCell(new Label(column++, row, result.getKeyId()));
                sheet.addCell(new Label(column++, row, statisticsMapper.findAdvertiseKey(result.getFmId())));
                sheet.addCell(new Label(column++, row, result.getTotalCount().toString()));
                sheet.addCell(new Label(column++, row, result.getZoneCounts().get(1).getCount().toString()));
                sheet.addCell(new Label(column++, row, result.getZoneCounts().get(2).getCount().toString()));
                sheet.addCell(new Label(column++, row, result.getZoneCounts().get(3).getCount().toString()));
                sheet.addCell(new Label(column++, row, result.getZoneCounts().get(0).getCount().toString()));
                sheet.addCell(new Label(column++, row, resultLike.get(row - 1).getTotalCount().toString()));
                sheet.addCell(new Label(column++, row, resultLike.get(row - 1).getZoneCounts().get(1).getCount().toString()));
                sheet.addCell(new Label(column++, row, resultLike.get(row - 1).getZoneCounts().get(2).getCount().toString()));
                sheet.addCell(new Label(column++, row, resultLike.get(row - 1).getZoneCounts().get(3).getCount().toString()));
                sheet.addCell(new Label(column++, row, resultLike.get(row - 1).getZoneCounts().get(0).getCount().toString()));
                ++row;
            }
            //  写入数据并关闭文件
            book.write();
            book.close();
            return fileName;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private List <FMDetailLikeResult> fmDetail(LocalDate date, FMChannel fmChannel, StatisticsType type) {
        List <FMDetailLikeResult> resultList = statisticsMapper.findPlayMusicExcel(date, fmChannel);
        resultList.forEach(result -> {
            List <ZoneCount> zoneCountList;
            if (type.equals(StatisticsType.LIKE)) {
                zoneCountList = statisticsMapper.findLikeCount(result.getFmId());
            } else {
                zoneCountList = statisticsMapper.findListenCount(result.getFmId());
            }
            List <ZoneCount> saveList = this.save(zoneCountList);
            result.setZoneCounts(saveList);
            result.setTotalCount(zoneCountList.stream()
                    .mapToInt(zoneLikeCount -> {
                        return zoneLikeCount.getCount();
                    }).sum());

        });
        return resultList;
    }

    private String createExcel(List <FMDetailLikeResult> results, ExcelFileRequest request) {
        try {
            String fileName = "statistics.xls";
            File file = new File(path);
            if (!file.exists()) {
                file.mkdirs();
            }
            //  打开文件
            WritableWorkbook book = Workbook.createWorkbook(new File(path + "/", fileName));
            //  生成名为“第一页”的工作表，参数0表示这是第一页
            WritableSheet sheet = book.createSheet(" 第一页 ", 0);

            //  将定义好的单元格添加到工作表中  在Label对象的构造子中指名单元格位置是第一列第一行(0,0)
            sheet.addCell(new Label(0, 0, "Time"));
            sheet.addCell(new Label(1, 0, "Segment ID-Name"));
            sheet.addCell(new Label(2, 0, "Total"));
            sheet.addCell(new Label(3, 0, "EST"));
            sheet.addCell(new Label(4, 0, "CST"));
            sheet.addCell(new Label(5, 0, "MST"));
            sheet.addCell(new Label(6, 0, "PST"));

            int row = 1;
            for (FMDetailLikeResult result : results) {
                int column = 0;
                sheet.addCell(new Label(column++, row, result.getStartTime().toLocalTime().toString() + "-" + result.getEndTime().toLocalTime().toString()));
                sheet.addCell(new Label(column++, row, result.getKeyId() + "-" + result.getSingerName() + "-" + result.getMusicTitle()));
                sheet.addCell(new Label(column++, row, result.getTotalCount().toString()));
                sheet.addCell(new Label(column++, row, result.getZoneCounts().get(0).getCount().toString()));
                sheet.addCell(new Label(column++, row, result.getZoneCounts().get(3).getCount().toString()));
                sheet.addCell(new Label(column++, row, result.getZoneCounts().get(2).getCount().toString()));
                sheet.addCell(new Label(column++, row, result.getZoneCounts().get(1).getCount().toString()));

                ++row;
            }
            //  写入数据并关闭文件
            book.write();
            book.close();
            return fileName;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private List <ZoneCount> save(List <ZoneCount> zoneCountList) {
        List <ZoneCount> saveList = this.initSaveList();
        zoneCountList.forEach(zoneLikeCount -> {
            ZoneCount likeCount = new ZoneCount();
            switch (zoneLikeCount.getZoneType()) {
                case EST:
                    likeCount.setZoneType(TimeZoneType.EST);
                    likeCount.setCount(zoneLikeCount.getCount());
                    saveList.remove(0);
                    saveList.add(0, likeCount);
                    break;
                case PST:
                    likeCount.setZoneType(TimeZoneType.PST);
                    likeCount.setCount(zoneLikeCount.getCount());
                    saveList.remove(1);
                    saveList.add(1, likeCount);
                    break;
                case MST:
                    likeCount.setZoneType(TimeZoneType.MST);
                    likeCount.setCount(zoneLikeCount.getCount());
                    saveList.remove(2);
                    saveList.add(2, likeCount);
                    break;
                case CST:
                    likeCount.setZoneType(TimeZoneType.CST);
                    likeCount.setCount(zoneLikeCount.getCount());
                    saveList.remove(3);
                    saveList.add(3, likeCount);
                    break;
                default:
                    break;
            }
        });
        return saveList;
    }

    private List <ZoneCount> initSaveList() {
        List <ZoneCount> saveList = new ArrayList <>();
        ZoneCount initEST = new ZoneCount();
        initEST.setZoneType(TimeZoneType.EST);
        initEST.setCount(0);
        ZoneCount initPST = new ZoneCount();
        initPST.setZoneType(TimeZoneType.PST);
        initPST.setCount(0);
        ZoneCount initMST = new ZoneCount();
        initMST.setZoneType(TimeZoneType.MST);
        initMST.setCount(0);
        ZoneCount initCST = new ZoneCount();
        initCST.setZoneType(TimeZoneType.CST);
        initCST.setCount(0);
        saveList.add(0, initEST);
        saveList.add(1, initPST);
        saveList.add(2, initMST);
        saveList.add(3, initCST);
        return saveList;
    }
}
